#pragma once

#include<iostream>
#include"Thread.hpp"
#include<unistd.h>
#include<vector>
#include<queue>
#include<string>
#include<functional>
#include "Log.hpp"

using namespace std;
using namespace ThreadMoudle;

static const int gdefaultnum = 5;

void test()
{
    while (true)
    {
        std::cout << "hello world" << std::endl;
        sleep(1);
    }
}

template<typename T>
class ThreadPool
{
    private:
        void LockQueue()//任务队列加锁
        {
            pthread_mutex_lock(&_mutex);
        }
        void UnlockQueue()//任务队列解锁
        {
            pthread_mutex_unlock(&_mutex);
        }
        void Wakeup()//唤醒线程
        {
            pthread_cond_signal(&_cond);
        }
        bool IsEmpty()//判断队列是否为空
        {
            return _task_queue.empty();
        }
        void WakeupAll()//唤醒所有线程
        {
            pthread_cond_broadcast(&_cond);
        }
        void Sleep()//线程休眠
        {
            pthread_cond_wait(&_cond, &_mutex);
        }
        void HandlerTask()
        {
            while(true)
            {
                //取任务
                LockQueue();
                while(IsEmpty()&&_isrunning)
                {
                    Sleep();
                }

                // 判定一种情况
                if (IsEmpty() && !_isrunning)
                {
                    UnlockQueue();
                    break;
                }

                T t = _task_queue.front();//取任务
                _task_queue.pop();
                UnlockQueue();

                //处理任务
                t();//处理任务，此处不用/不能在临界区中处理
            }
        }
    public:
        ThreadPool(int thread_num = gdefaultnum):_thread_num(gdefaultnum),_isrunning(false),_sleep_thread_num(0)
        {
            pthread_mutex_init(&_mutex, nullptr);
            pthread_cond_init(&_cond, nullptr);
        }

        void Init()//线程初始化
        {
            func_t func = std::bind(&ThreadPool::HandlerTask, this);//让this和函数强关联，构建了一个新的方法func
            for(int i=0;i<_thread_num;i++)
            {
                string threadname="thread-"+to_string(i+1);
                _threads.emplace_back(threadname,func);//启动时调用函数
            }
        }

        void Start()//线程启动
        {
            _isrunning=true;
            for(auto& thread:_threads)//一键启动所有线程
            {
                thread.Start();
            }
        }

        void Stop()//线程终止
        {
            LockQueue();
            _isrunning = false;
            WakeupAll();
            UnlockQueue();
        }

        void Equeue(const T& in)//推送任务
        {
            LockQueue();
            if(_isrunning)
                _task_queue.push(in);
                if(_sleep_thread_num>0)
                {
                    Wakeup();
                }
            UnlockQueue();
        }

        ~ThreadPool()
        {
            pthread_mutex_destroy(&_mutex);
            pthread_cond_destroy(&_cond);
        }
    private:
        int _thread_num;//线程池个数
        vector<Thread> _threads;//线程池
        queue<T> _task_queue;//任务队列,共享资源
        bool _isrunning;//线程是否在运行

        int _sleep_thread_num;
        pthread_mutex_t _mutex;//加锁
        pthread_cond_t _cond;//条件变量

};